package kalc.deuxdee;

import iteracon.generator.Range;
import java.util.Iterator;

/*
 * index 2d calculator
 * that map coordinate
 * from 2d coordinate
 * to unidimensional
 * array.
 * \_________________/
 *      /
 * \ ('<
 * (<=)
 *
 * What wrong with simple
 * 2d array ?
 * \____________________/
 *             \
 *              >') /
 *               (=>)
 *
 * THEY ARE AWFULL !!!!!
 * its not just a 2d array
 * but an array of array
 * were the fist contain
 * reference to the other
 * array. it simply take
 * more place than a simple
 * 2d array.
 * \____________________/
 *      /
 * \ (@<
 * (<=)
 * */
/**
 * @author martin
 *index 2d calculator
 */
public class Index2d implements DeuxDee {
	private final int _w,
	                  _h;

	/**
	 * private constructor
	 * @param w as width
	 * @param h as height
	 */
	private Index2d(int w, int h){
		_w = w;
		_h = h;
	}

	/**
	 * static factory
	 * from rectangle size
	 * @param w as width
	 * @param h as coordinate
	 * @return new index 2d calculator
	 */
	public static Index2d fromRect(int w, int h){
		if (w < 1 || h < 1)
			throw new IllegalArgumentException();
		return new Index2d(w,h);
	}

	/**
	 * static factory
	 * from square size
	 * @param w as width
	 * @return new index 2d calculator
	 */
	public static Index2d fromSqr(int w){
		if (w < 1)
			throw new IllegalArgumentException();
		return new Index2d(w,w);
	}

	/**
	 * getter size
	 * @return size
	 */
  @Override
	public int size(){
		return _w*_h;
	}

	/**
	 * getter index
	 * @param x
	 * @param y
	 * @return index from x,y
	 */
  @Override
	public int index(int x, int y){
		if (x < 0 || x > _w || y < 0 || y > _h)
			throw new ArrayIndexOutOfBoundsException();
		return x + y * _w;
	}

	/**
	 * getter x
	 * @param index
	 * @return x from index
	 */
  @Override
	public int x(int index){
		if (index > size())
			throw new ArrayIndexOutOfBoundsException();
		return index % _w;
	}

	/**
	 * getter y
	 * @param index
	 * @return y from index
	 */
  @Override
	public int y(int index){
		if (index > size())
			throw new ArrayIndexOutOfBoundsException();
		return index / _w;
	}

	/**
	 * getter width
	 * @return width
	 */
  @Override
	public int w(){
		return _w;
	}

	/**
	 * getter h
	 * @return heigth
	 */
  @Override
	public int h(){
		return _h;
	}

  @Override
  public Iterator<Integer> iterator() {
    return Range.fromZero(size()).iterator();
  }
}
